//! Defines the Abstract Syntax Tree (AST) for the MATLAB language.

/// A unique identifier for a variable, function, etc.
pub type Ident = String;

/// The root of the AST, representing a whole file or script.
#[derive(Debug, Clone, PartialEq)]
pub struct Program {
    pub statements: Vec<Statement>,
}

/// Represents a single statement in MATLAB.
#[derive(Debug, Clone, PartialEq)]
pub enum Statement {
    /// An assignment, e.g., `x = 5;`
    Assignment {
        left: Expression,
        right: Expression,
    },
    /// A statement that is just an expression, e.g., a function call `disp('hello')`
    Expression(Expression),
    /// A function definition.
    FunctionDef {
        name: Ident,
        args: Vec<Ident>,
        return_vars: Vec<Ident>,
        body: Vec<Statement>,
    },
    /// A placeholder for statements not yet implemented.
    NotImplemented(String),
}

/// Represents an expression that can be evaluated to a value.
#[derive(Debug, Clone, PartialEq)]
pub enum Expression {
    /// A literal value, like a number or a string.
    Literal(Literal),
    /// An identifier, like a variable name.
    Identifier(Ident),
    /// A binary operation, e.g., `a + b`.
    BinaryOp {
        op: BinaryOp,
        left: Box<Expression>,
        right: Box<Expression>,
    },
    /// A unary operation, e.g., `-x` or `~x`.
    UnaryOp {
        op: UnaryOp,
        expr: Box<Expression>,
    },
    /// A function call, e.g., `my_func(arg1, arg2)`.
    FunctionCall {
        name: Ident,
        args: Vec<Expression>,
    },
    /// A matrix definition, e.g., `[1, 2; 3, 4]`.
    Vector(Vector),
}

/// Represents a vector or matrix. Each inner vector is a row.
#[derive(Debug, Clone, PartialEq)]
pub struct Vector(pub Vec<Vec<Expression>>);

/// Represents a literal value.
#[derive(Debug, Clone, PartialEq)]
pub enum Literal {
    Number(f64),
    String(String),
}

/// Represents a binary operator.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum BinaryOp {
    Add,      // +
    Sub,      // -
    Mul,      // *
    Div,      // /
    Pow,      // ^
    Eq,       // ==
    NotEq,    // ~=
    Lt,       // <
    Lte,      // <=
    Gt,       // >
    Gte,      // >=
    And,      // &&
    Or,       // ||
}

/// Represents a unary operator.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum UnaryOp {
    Negate, // -
    Not,    // ~
}
